//引用和借用
pub fn reference_test(){

    /*
        概念: 引用是变量的一种“别名”，它并不拥有数据的所有权，只是提供了对原始数据的访问权限。 
        类型: 和大多数编程语言类似，引用有多种形式。其中包括&T（不可变引用）和&mut T（可变引用），也包括与生命周期相关的更复杂的引用。
        
     */

    //不可变引用
    let str=String::from("reference");
    let len= reference_test_1(&str);
    println!("reference_test-{len}");

    //可变引用
    let mut  str=String::from("我是靓仔!");
    println!("{str}");
    reference_test_mut(& mut str);
    println!("{str}");

    let str: &mut String =& mut str;
   //let stwr: &mut String =& mut str;
    
    println!("{str}");
    reference_test_mut(str);
    println!("{str}");
    /*
    需要注意的是，我们不能在同一时间多次将 str 作为可变变量借用
    这是因为 rust 要避免数据竞争的问题

    数据竞争（data race）类似于竞态条
    件，它可由这三个行为造成：
    • 两个或更多指针同时访问同一数据。
    • 至少有一个指针被用来写入数据。
    • 没有同步数据访问的机制。
    数据竞争会导致未定义行为，难以在运行时追踪，并且难以诊断和修复；Rust 避免了这种情
    况的发生，因为它甚至不会编译存在数据竞争的代码！

    */
    //let  str =& mut str;

    /*
      话又说回来，如果我们确实是需要 重复借用 该怎么办呢？ 之前我们有了解过作用域 的概念， 当 变量离开作用域后 他
      的所有权就会被释放
      
     */

    //所以我们可以
     
        let mut  str=String::from("我是big靓仔!");
        println!("{str}");
        reference_test_mut(& mut str);
        println!("{str}");
        reference_test_mut(& mut str);
        println!("{str}");
        reference_test_mut(& mut str);
        println!("{str}");
        reference_test_mut(& mut str);
        println!("{str}");
     
     //也可以
       let mut str:String =String::from("我是big靓仔1111!");
       let t:&mut String  = & mut str;
       println!("{t}");
       let t1:&mut String = & mut str;
       println!("{t1}");
       reference_test_mut(& mut str);
       println!("{str}");

       /* 
       //同一个变量不能同时有多个可变引用（或是一个可变引用与任何不可变引用）。
       let mut test=String::from("12345");
       let t2=&test;
       let t4=&test;
       let t3= &mut  test;
       println!("{}, {}, and", t2, t4);

       let mut test=String::from("12345");
       let t2=&mut test;
       let t4=&test;
      // let t3= &mut  test;
       println!("{}, {}, and", t2, t4);
        */

        let mut test=String::from("12345");
       let t2=&test;
       let t4=&test;
       println!("{}, {}, and", t2, t4);
        {
        let t3= &mut  test;
        t3.push_str(("......"));
        println!("{t3}");
        }
    
      
}

pub  fn reference_test_mut(str:& mut String){
   
   str.push_str("哈哈哈哈哈");
   
}
pub fn reference_test_2(str:String)->usize{
str.len()
}

pub fn reference_test_1(str:&String)->usize{

    //let len: usize= str.len();
    //return  len;


    str.len()

  

}

